GitHub ActionsでDockerレイヤーキャッシュを利用したい
こんにちは!コンサル部のinomaso(@inomasosan)です。
GitHub ActionsのCI/CDはVM上でワークフローが実行されるため、同じイメージであってもキャッシュを利用することなく最初からビルドが実行されます。
ワークフローが実行されるたびに、ベースとなるイメージのダウンロードやファイルコピーが実行されてしまうと、デプロイ時間が伸びてしまうので改善が必要です。
そこで今回は前回作成したGitHub Actionsワークフローに、Dockerレイヤーキャッシュを追加していきます。
どのActionsを追加するか
今回はdocker/build-push-actionというDockerイメージのビルドからプッシュ + キャッシュをいい感じに実行してくれるActionsを利用していきます。
上記ActionsのCacheのドキュメントに、以下のサンプルコードがあるので、こちらを参考にしていきます。
name: ci on: push: branches: - 'master' jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Cache Docker layers uses: actions/cache@v2 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx- - name: Login to DockerHub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v2 with: context: . push: true tags: user/app:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - # Temp fix # https://github.com/docker/build-push-action/issues/252 # https://github.com/moby/buildkit/issues/1896 name: Move cache run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache
GitHub Actionsワークフロー修正
前回作成したワークフローを元に修正していきます。
以下がワークフローの全体で、修正した箇所をハイライトしました。
# This workflow will build and push a new container image to Amazon ECR, # and then will deploy a new task definition to Amazon ECS, when there is a push to the main branch. # # To use this workflow, you will need to complete the following set-up steps: # # 1. Create an ECR repository to store your images. # For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`. # Replace the value of the `ECR_REPOSITORY` environment variable in the workflow below with your repository's name. # Replace the value of the `AWS_REGION` environment variable in the workflow below with your repository's region. # # 2. Create an ECS task definition, an ECS cluster, and an ECS service. # For example, follow the Getting Started guide on the ECS console: # https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun # Replace the value of the `ECS_SERVICE` environment variable in the workflow below with the name you set for the Amazon ECS service. # Replace the value of the `ECS_CLUSTER` environment variable in the workflow below with the name you set for the cluster. # # 3. Store your ECS task definition as a JSON file in your repository. # The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`. # Replace the value of the `ECS_TASK_DEFINITION` environment variable in the workflow below with the path to the JSON file. # Replace the value of the `CONTAINER_NAME` environment variable in the workflow below with the name of the container # in the `containerDefinitions` section of the task definition. # # 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. # See the documentation for each action used below for the recommended IAM policies for this IAM user, # and best practices on handling the access key credentials. name: Deploy to Amazon ECS on: push: branches: - main env: AWS_REGION: ap-northeast-1 # set this to your preferred AWS region, e.g. us-west-1 ECR_REPOSITORY: githubactions-httpd # set this to your Amazon ECR repository name ECS_SERVICE: httpd-service # set this to your Amazon ECS service name ECS_CLUSTER: httpd-cluster # set this to your Amazon ECS cluster name ECS_TASK_DEFINITION: task-definition.json # set this to the path to your Amazon ECS task definition # file, e.g. .aws/task-definition.json CONTAINER_NAME: httpd-container # set this to the name of the container in the # containerDefinitions section of your task definition AWS_ROLE_ARN: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GitHubActionsOIDC # GitHub用に作成したIAMロールのARN jobs: deploy: name: Deploy runs-on: ubuntu-latest environment: production # These permissions are needed to interact with GitHub's OIDC Token endpoint. permissions: id-token: write contents: read steps: - name: Checkout uses: actions/checkout@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Cache Docker layers uses: actions/cache@v2 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx- - name: Configure AWS credentials of IAM Role uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: ${{ env.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - uses: docker/build-push-action@v2 id: build-image with: push: true tags: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Move cache run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache - name: Fill in the new image ID in the Amazon ECS task definition id: task-def uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: ${{ env.ECS_TASK_DEFINITION }} container-name: ${{ env.CONTAINER_NAME }} image: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }} - name: Deploy Amazon ECS task definition uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: task-definition: ${{ steps.task-def.outputs.task-definition }} service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} wait-for-service-stability: true
ワークフロー実行結果確認
1回目
docker/build-push-action
に9秒程時間がかかりました。
以下はログの抜粋となりますが、最初からビルドしていることがわかります。
#4 [1/2] FROM docker.io/library/httpd:latest@sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32 #4 resolve docker.io/library/httpd:latest@sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32 done #4 sha256:d982c879c57eba6fa5c08ea1e9811442ec89196c9a5793cc9db6e28b60dfff88 297B / 297B 0.0s done #4 sha256:dcc4698797c83ed22cecf9babcfc5c5abd15c5f86b73f688d65c4334e1632e1e 177B / 177B 0.0s done #4 sha256:41c22baa66ecf728c1ea0c5405ebe72c5b2606ef66b4565a209e23e1ab05fe80 915.38kB / 915.38kB 0.1s done #4 sha256:67283bbdd4a0dd32f555b4279fd546b3c69251342f0c6715b075cc72049d28a1 11.53MB / 24.13MB 0.2s #4 sha256:67283bbdd4a0dd32f555b4279fd546b3c69251342f0c6715b075cc72049d28a1 24.13MB / 24.13MB 0.3s #4 sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea 7.34MB / 31.36MB 0.2s #4 sha256:67283bbdd4a0dd32f555b4279fd546b3c69251342f0c6715b075cc72049d28a1 24.13MB / 24.13MB 0.3s done #4 sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea 31.36MB / 31.36MB 0.3s #4 sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea 31.36MB / 31.36MB 0.5s done #4 extracting sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea #4 extracting sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea 1.1s done #4 extracting sha256:dcc4698797c83ed22cecf9babcfc5c5abd15c5f86b73f688d65c4334e1632e1e 0.0s done #4 extracting sha256:41c22baa66ecf728c1ea0c5405ebe72c5b2606ef66b4565a209e23e1ab05fe80 0.0s done #4 DONE 1.6s #4 [1/2] FROM docker.io/library/httpd:latest@sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32 #4 extracting sha256:67283bbdd4a0dd32f555b4279fd546b3c69251342f0c6715b075cc72049d28a1 #4 extracting sha256:67283bbdd4a0dd32f555b4279fd546b3c69251342f0c6715b075cc72049d28a1 0.6s done #4 extracting sha256:d982c879c57eba6fa5c08ea1e9811442ec89196c9a5793cc9db6e28b60dfff88 done #4 DONE 2.2s #5 [2/2] COPY ./html /usr/local/apache2/htdocs/ #5 DONE 0.8s
2回目
docker/build-push-action
は6秒程ほどに時間が短縮されました
以下はログの抜粋となりますが、キャッシュを利用していることがわかります。
#4 [1/2] FROM docker.io/library/httpd:latest@sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32 #4 resolve docker.io/library/httpd:latest@sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32 done #4 DONE 0.0s #6 importing cache manifest from local:3587489754217729963 #6 DONE 0.0s #5 [2/2] COPY ./html /usr/local/apache2/htdocs/ #5 CACHED
ハマったこと
docker/build-push-action
を実行するにあたり、GitHub ActionsからECSとECRへのCI/CDを最小権限で実行したいのIAMポリシーを利用したのですが、権限不足でエラーになってしまいました。
もし最小権限で実行している場合は、以下のブログをご参照願います。
あわせて読みたい
まとめ
GitHub Actionsは色々と便利なActionsが多いので、ゴリゴリにCLIを書かなくても簡単にCI/CDを実行できるのは本当にありがたいですね!
この記事が、どなたかのお役に立てば幸いです。それでは!